﻿using InkjetControl.codec;
using InkjetControl.events;
using InkjetControl.NLog;
using System;
using System.ComponentModel;
using System.Windows.Input;
using InkjetControl.bean;
using System.Collections.Generic;
using MaterialDesignThemes.Wpf;
using InkjetControl.view;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using System.Text;
//using Windows.UI.Notifications;
//using Windows.Data.Xml.Dom;
using System.Windows;
using Microsoft.Toolkit.Uwp.Notifications;

namespace InkjetControl.model
{
    public class DeviceItemModel : ViewModelBase
    {


        public DeviceItemModel(string deviceId, string deviceName)
        {
            DeviceId = deviceId;
            DeviceName = deviceName;
            StatusModel = new StatusModel();
            PrintParamsModel = new PrintParamsModel(deviceId);
            _selectedFontSize = FontSize.SIZE7X10;
            PrintCommand = new AnotherCommandImplementation(_ =>
            {
                Log.Logger.Info("PrintCommand");
                if (StatusModel.EquipmentState >= EquipmentState.DONE_INK)
                {
                    if (!IsPrinting)
                    {
                        MsgDialogInfoModel dialogInfoModel = new MsgDialogInfoModel()
                        {
                            Msg = "是否启动所有设备喷印，按确定按钮将启动开始喷印，否则请按取消按钮",
                            IsShowCancelBtn = Visibility.Visible,
                            IsShowCloseBtn = Visibility.Hidden,
                            IsShowConfirmBtn = Visibility.Visible
                        };
                        dialogInfoModel.OnDialogConfirmBtnHandler += StartPrint_OnDialogConfirmBtnHandler;
                        MsgDialog msgDialog = new MsgDialog()
                        {
                            DataContext = dialogInfoModel
                        };
                        _ = DialogHost.Show(msgDialog);
                    }
                    else
                    {
                        MsgDialogInfoModel dialogInfoModel = new MsgDialogInfoModel()
                        {
                            Msg = "是否需要所有设备停止喷印，点确认即将所有设备停止喷印操作，否则请按取消按钮",
                            IsShowCancelBtn = Visibility.Visible,
                            IsShowCloseBtn = Visibility.Hidden,
                            IsShowConfirmBtn = Visibility.Visible
                        };
                        dialogInfoModel.OnDialogConfirmBtnHandler += StopPrint_OnDialogConfirmBtnHandler;
                        MsgDialog msgDialog = new MsgDialog()
                        {
                            DataContext = dialogInfoModel
                        };
                        _ = DialogHost.Show(msgDialog);
                    }

                }

            });

            SuppyInkCommand = new AnotherCommandImplementation(_ =>
            {
                Log.Logger.Info("SuppyInkCommand");

                if (StatusModel.EquipmentState != EquipmentState.STOPPED)
                {

                    MsgDialogInfoModel dialogInfoModel = new MsgDialogInfoModel()
                    {
                        Msg = "是否将所有设备停止供墨操作，如确认执行停止供墨操作请按确定按钮，否则请按取消按钮",
                        IsShowCancelBtn = Visibility.Visible,
                        IsShowCloseBtn = Visibility.Hidden,
                        IsShowConfirmBtn = Visibility.Visible
                    };
                    dialogInfoModel.OnDialogConfirmBtnHandler += StopSuppyInk_OnDialogConfirmBtnHandler;
                    MsgDialog msgDialog = new MsgDialog()
                    {
                        DataContext = dialogInfoModel
                    };
                    _ = DialogHost.Show(msgDialog);
                }
                else
                {
                    MsgDialogInfoModel dialogInfoModel = new MsgDialogInfoModel()
                    {

                        Msg = "是否启动所有设备供墨，确认开始供墨，取消不执行",
                        IsShowCancelBtn = Visibility.Visible,
                        IsShowCloseBtn = Visibility.Hidden,
                        IsShowConfirmBtn = Visibility.Visible
                    };
                    dialogInfoModel.OnDialogConfirmBtnHandler += StartSuppyInk_OnDialogConfirmBtnHandler;
                    MsgDialog msgDialog = new MsgDialog()
                    {
                        DataContext = dialogInfoModel
                    };
                    _ = DialogHost.Show(msgDialog);

                }

            });

            PrintParamsSetCommand = new AnotherCommandImplementation(async _ =>
            {
                Message msg = new Message
                {
                    MachineCode = DeviceId,
                    MachineLabel = DeviceName,
                    MessageType = MessageType.REQUEST,
                    Body = Message.GenerateMsgBody(NetCmd.GET_PRINT_PARAMS)
                };
                EventBus.SendMsgHandler(DeviceId, msg);


                PrintParamsSetControl paramsDialog = new PrintParamsSetControl()
                {
                    DataContext = PrintParamsModel
                };

                object result = await DialogHost.Show(paramsDialog, "RootDialog", ClosingEventHandler);

            });

            ImportTextCommand = new AnotherCommandImplementation(_ =>
            {
                ImportTextDialog();

            });
            ImportImageCommand = new AnotherCommandImplementation(_ =>
            {
                ImportImageDialog();
            });

            UpdateContentCommand = new AnotherCommandImplementation(_ =>
            {

                if (!string.IsNullOrEmpty(PrintContent))
                {
                    Message msg = new Message
                    {
                        MachineCode = DeviceId,
                        MachineLabel = DeviceName,
                        MessageType = MessageType.REQUEST,
                    };
                    PrintDataBean printData = new PrintDataBean
                    {
                        Type = (int)ElementType.TEXT,
                        FontSize = (int)_selectedFontSize,
                        Text = PrintContent
                    };
                    msg.Body = Message.GenerateMsgBody(NetCmd.UPDATE_CONTENT, ref printData);
                    EventBus.SendMsgHandler(DeviceId, msg);
                }
                else
                {
                    MsgDialog msgDialog = new MsgDialog()
                    {
                        DataContext = new MsgDialogInfoModel()
                        {
                            Msg = "内容为空不能喷印"
                        }
                    };
                    _ = DialogHost.Show(msgDialog);
                }
            });

            BitmapFontSizes = new List<FontSize>
            {
                FontSize.NONE,
                FontSize.SIZE5X5,
                FontSize.SIZE5X7,
                FontSize.SIZE5X7A,
                FontSize.SIZE7X9,
                FontSize.SIZE7X10,
                FontSize.SIZE8X12,
                FontSize.SIZE9X12,
                FontSize.SIZE11X15,
                FontSize.SIZE15X19,
                FontSize.SIZE17X24,
                FontSize.SIZE21X28,
                FontSize.SIZE24X33
            };

            ElementTypeList = new List<ElementType>
            {
                ElementType.NONE,
                ElementType.TEXT,
                ElementType.PICTURE,
                ElementType.SHIFT,
                ElementType.DATE,
                ElementType.SEQUENCE_NUMBER,
                ElementType.CODE,
                ElementType.DATA,
                ElementType.SCAN_GUN,
                ElementType.NOTE,
                ElementType.CHECK_CODE

            };

            EventBus.OnPrintParamsSetHandler += EventBus_OnPrintParamsSetHandler;
            EventBus.OnPrintParamsGetHandler += EventBus_OnPrintParamsGetHandler;

            EventBus.OnStartPrintHandler += EventBus_OnStartPrintHandler; ;
            EventBus.OnStopPrintHandler += EventBus_OnStopPrintHandler;

            EventBus.OnStartSupplyInkHandler += EventBus_OnStartSupplyInkHandler;
            EventBus.OnStopSupplyInkHandler += EventBus_OnStopSupplyInkHandler;

            EventBus.OnStatusRefreshHandler += EventBus_OnStatusRefreshHandler;
        }

        private void StartSuppyInk_OnDialogConfirmBtnHandler()
        {
            Message msg = new Message
            {
                MachineCode = DeviceId,
                MachineLabel = DeviceName,
                MessageType = MessageType.REQUEST,
            };

            msg.Body = Message.GenerateMsgBody(NetCmd.START_SUPPLY_INK);
            EventBus.SendMsgHandler(DeviceId, msg);

        }

        private void StopSuppyInk_OnDialogConfirmBtnHandler()
        {
            Message msg = new Message
            {
                MachineCode = DeviceId,
                MachineLabel = DeviceName,
                MessageType = MessageType.REQUEST,
            };

            bool isQuickyStop = false;
            msg.Body = Message.GenerateMsgBody(NetCmd.STOP_SUPPLY_INK, ref isQuickyStop);
            EventBus.SendMsgHandler(DeviceId, msg);
        }

        private void StopPrint_OnDialogConfirmBtnHandler()
        {
            Message msg = new Message
            {
                MachineCode = DeviceId,
                MachineLabel = DeviceName,
                MessageType = MessageType.REQUEST,
            };
            msg.Body = Message.GenerateMsgBody(NetCmd.STOP_PRINT);
            EventBus.SendMsgHandler(DeviceId, msg);
        }

        private void StartPrint_OnDialogConfirmBtnHandler()
        {
            Message msg = new Message
            {
                MachineCode = DeviceId,
                MachineLabel = DeviceName,
                MessageType = MessageType.REQUEST,
            };
            msg.Body = Message.GenerateMsgBody(NetCmd.START_PRINT);
            EventBus.SendMsgHandler(DeviceId, msg);
        }

        private void ClosingEventHandler(object sender, DialogClosingEventArgs eventArgs)
            => Console.WriteLine("You can intercept the closing event, and cancel here.");

        private void EventBus_OnStatusRefreshHandler(string machineCode, StatusBean status, string machineLabel)
        {
            if (machineCode == DeviceId)
            {
                DeviceName = machineLabel;

                StatusModel.PhaseAngle = status.PhaseAngle;
                StatusModel.PhaseValue = status.PhaseValue;
                StatusModel.Viscosity = status.Viscosity;
                StatusModel.HighVoltage = status.HighVoltage;
                StatusModel.Pressure = status.Pressure;
                StatusModel.InkCylinder = status.InkCylinder;
                StatusModel.ViscosityCylinder = status.ViscosityCylinder;
                StatusModel.SolventCylinder = status.SolventCylinder;
                StatusModel.MixCylinder = status.MixCylinder;
                StatusModel.FlightTime = status.FlightTime;

                StatusModel.MixTemplature = status.MixTemp;
                StatusModel.NozzleTemplature = status.NozzleTemp;
                StatusModel.ChassisTemplature = status.ChassisTemp;

                StatusModel.SupplyInkState = status.SupplyInkState;

                StatusModel.IsNozzleCoverFailure = status.IsNozzleCoverFailure;
                StatusModel.IsHighVoltageFailure = status.IsHighVoltageFailure;
                StatusModel.IsPhaseChargingFailure = status.IsPhaseChargingFailure;
                StatusModel.IsPhaseFailure = status.IsPhaseFailure;
                StatusModel.IsRecycleFailure = status.IsRecycleFailure;

                StatusModel.EquipmentState = (EquipmentState)status.DevState;

                StatusModel.PrintDone = status.PrintDone;
                StatusModel.PrintCount = status.PrintCount;

                IsInkSupplied = StatusModel.EquipmentState >= EquipmentState.DONE_INK;
                IsPrinting = StatusModel.EquipmentState == EquipmentState.PRINTING;
            }
        }


        private void EventBus_OnStartPrintHandler(string machineCode, string info)
        {
            if (!string.IsNullOrEmpty(info))
            {
                System.Windows.Application.Current.Dispatcher.Invoke(() =>
                {
                    MsgDialog dialog = new MsgDialog { DataContext = new MsgDialogInfoModel() { Msg = info } };
                    DialogHost.Show(dialog);
                });
            }
        }

        private void EventBus_OnStopPrintHandler(string machineCode)
        {

        }

        private void EventBus_OnStopSupplyInkHandler(string machineCode)
        {

        }

        private void EventBus_OnStartSupplyInkHandler(string machineCode)
        {

        }

        private void EventBus_OnPrintParamsSetHandler(string machineCode)
        {

        }

        private void EventBus_OnPrintParamsGetHandler(string machineCode, PrintParamsBean printParams)
        {
            if (machineCode == DeviceId)
            {

                PrintParamsModel.IsChanged = false;

                PrintParamsModel.FontWidth = printParams.FontWidth;
                PrintParamsModel.FontHeight = printParams.FontHeight;
                PrintParamsModel.FontBold = printParams.FontBold;
                PrintParamsModel.PrintMode = printParams.PrintMode;
                PrintParamsModel.VerticalLattice = printParams.VerticalLattice;
                PrintParamsModel.PrintSpacing = printParams.PrintSpacing;
                PrintParamsModel.PrintTimes = printParams.PrintTimes;
                PrintParamsModel.UpsideDown = printParams.UpsideDown;
                PrintParamsModel.SyncMode = printParams.SyncMode;
                PrintParamsModel.SyncColumnSpacing = printParams.SyncColumnSpacing;
                PrintParamsModel.PrintDelay = printParams.PrintDelay;
                PrintParamsModel.ReversePrintDelay = printParams.ReversePrintDelay;
                PrintParamsModel.ReverseFontWidth = printParams.ReverseFontWidth;
                PrintParamsModel.ReverseFontHeight = printParams.ReverseFontHeight;
                PrintParamsModel.ElectricEye1Direction = printParams.ElectricEye1Direction;
                PrintParamsModel.ElectricEye2Direction = printParams.ElectricEye2Direction;
                PrintParamsModel.ElectricEye1Level = printParams.ElectricEye1Level;
                PrintParamsModel.ElectricEye2Level = printParams.ElectricEye2Level;
                PrintParamsModel.ReverseUpsideDown = printParams.ReverseUpsideDown;
                PrintParamsModel.ReversePrintMode = printParams.ReversePrintMode;
                PrintParamsModel.ReversePrintTimes = printParams.ReversePrintTimes;
                PrintParamsModel.ReversePrintSpacing = printParams.ReversePrintSpacing;

                PrintParamsModel.IsChanged = true;
            }
        }

        public ICommand PrintCommand { get; }
        public ICommand SuppyInkCommand { get; }
        public ICommand PrintParamsSetCommand { get; }
        public ICommand ImportTextCommand { get; }
        public ICommand ImportImageCommand { get; }
        public ICommand UpdateContentCommand { get; }

        public PrintParamsModel PrintParamsModel { get; private set; }
        public StatusModel StatusModel { get; private set; }
        private string _deviceId;
        private string _deviceName;
        private string _printContent;
        private FontSize _selectedFontSize;

        private bool _isInkSupplied;
        private bool _isPrinting;
        private bool _isSelected;

        public IList<FontSize> BitmapFontSizes { get; }
        public IList<ElementType> ElementTypeList { get; }

        public bool IsInkSupplied
        {
            get => _isInkSupplied;
            set => SetProperty(ref _isInkSupplied, value);
        }

        public bool IsPrinting
        {
            get => _isPrinting;
            set => SetProperty(ref _isPrinting, value);
        }

        public FontSize SelectedFontSize
        {
            get => _selectedFontSize;
            set => SetProperty(ref _selectedFontSize, value);
        }

        public string PrintContent
        {
            get => _printContent;
            set => SetProperty(ref _printContent, value);
        }

        public bool IsSelected
        {
            get => _isSelected;
            set => SetProperty(ref _isSelected, value);
        }

        public string DeviceId
        {
            get => _deviceId;
            private set => SetProperty(ref _deviceId, value);
        }

        public string DeviceName
        {
            get => string.IsNullOrEmpty(_deviceName) ? DeviceId : _deviceName;
            private set => SetProperty(ref _deviceName, value);
        }

        public object EventBug { get; private set; }

        public void ImportTextDialog()
        {
            // 实例化一个文件选择对象
            Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
            dialog.DefaultExt = ".txt";  // 设置默认类型
            dialog.CheckFileExists = true;
            dialog.CheckPathExists = true;
            dialog.AddExtension = true;
            dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            dialog.Multiselect = false;
            // 设置可选格式
            dialog.Filter = @"文本文件|*.txt";

            dialog.Title = "选择文本:";

            // 打开选择框选择
            bool? result = dialog.ShowDialog();
            if (result == true)
            {
                string file = dialog.FileName; // 获取选择的文件名
                Log.Logger.Info("OpenDialog{0}", file);
                if (!File.Exists(file)) //先判断文件是否存在
                {
                    return;
                }

                FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);

                if (fs.Length > (1024 * 45))
                {
                    MsgDialog msgDialog = new MsgDialog()
                    {
                        DataContext = new MsgDialogInfoModel()
                        {
                            Msg = "文件过大",
                            IsShowCloseBtn = Visibility.Visible
                        }
                    };
                    _ = DialogHost.Show(msgDialog);
                    return;
                }

                StreamReader reader = new StreamReader(fs, Encoding.Default);
                string strReadline;
                List<string> contents = new List<string>();
                string showText = "";
                while ((strReadline = reader.ReadLine()) != null)
                {
                    contents.Add(strReadline);
                    showText += strReadline + "\n";
                }

                fs.Close();

                reader.Close();

                Log.Logger.Info("showText {0}", showText);
                //fs.Close();
                PrintDataBean printData = new PrintDataBean
                {
                    Contents = contents,
                    FontSize = (int)_selectedFontSize,
                    Type = (int)ElementType.DATA
                };

                Message msg = new Message
                {
                    MachineCode = DeviceId,
                    MessageType = MessageType.REQUEST,
                };

                msg.Body = Message.GenerateMsgBody(NetCmd.UPDATE_CONTENT, ref printData);
                EventBus.SendMsgHandler(DeviceId, msg);
            }
        }
        public void ImportImageDialog()
        {
            // 实例化一个文件选择对象
            Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog
            {
                CheckFileExists = true,
                CheckPathExists = true,
                AddExtension = true,
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                Multiselect = false,

                // 设置默认类型
                DefaultExt = ".png",
                // 设置可选格式
                Filter = @"图像文件(*.jpg,*.png,*.tif,*.gif,*.bmp)|*.jpeg;*.jpg;*.png;*.tif;*.tiff;*.gif;*.bmp
                            |BMP(*.bmp,*.dip,*.rle)|*.bmp;*.dip;*.rle
                            |JPEG(*.jpeg, *.jpg)|*.jpeg;*.jpg
                            |PNG(*.png)|*.png
                            |GIF(*.gif)|*.gif
                            |TIF(*.tif,*.tiff)|*.tif;*.tiff"
            };
            // 打开选择框选择
            bool? result = dialog.ShowDialog();
            if (result == true)
            {
                string file = dialog.FileName; // 获取选择的文件名
                Log.Logger.Info("OpenDialog{0}", file);
                Image img = Image.FromFile(file);


                MemoryStream memory = new MemoryStream();
                img.Save(memory, ImageFormat.Png);

                PrintDataBean printData = new PrintDataBean
                {
                    BmpWidth = img.Width,
                    BmpHeight = img.Height,
                    BmpBytes = new byte[memory.Length]
                };

                memory.Position = 0;
                int ret = memory.Read(printData.BmpBytes, 0, printData.BmpBytes.Length);
                memory.Close();
                memory.Dispose();
                GC.Collect();

                printData.Type = (int)ElementType.PICTURE;
                if (printData.BmpBytes.Length > (1024 * 50))
                {
                    MsgDialog msgDialog = new MsgDialog()
                    {
                        DataContext = new MsgDialogInfoModel()
                        {
                            Msg = "图片文件大于50k不能发送"
                        }
                    };
                    _ = DialogHost.Show(msgDialog);
                    return;
                }

                Message msg = new Message
                {
                    MachineCode = DeviceId,
                    MessageType = MessageType.REQUEST,
                };

                msg.Body = Message.GenerateMsgBody(NetCmd.UPDATE_CONTENT, ref printData);
                EventBus.SendMsgHandler(DeviceId, msg);
                ShowToast();
            }
        }

        private void ShowToast()
        {
            new ToastContentBuilder()
                .AddText("Adaptive Tiles Meeting", hintMaxLines: 1)
                .AddText("Conf Room 2001 / Building 135")
                .AddText("10:00 AM - 10:30 AM");
        }

        public void Destory()
        {
            try
            {
                if (DialogHost.IsDialogOpen("RootDialog"))
                {
                    DialogHost.Close("RootDialog");
                }
            }
            catch (Exception e)
            {
                Log.Logger.Warn(e, "Destory");
            }
        }



    }
}
